#!/usr/bin/env python
import sys
import os
import datetime
import time

###########################################################################
# configure these paths:
LOGFILE = '/var/log/ovimcored.log'
PIDFILE = '/var/run/ovimcored.pid'
###########################################################################

class Log:
    """file like for writes with auto flush after each write
    to ensure that everything is logged, even during an
    unexpected exit."""
    def __init__(self, f):
        self.f = f
    def write(self, s):
        self.f.write(s)
        self.f.flush()
 
class OVIMCore:
    def log_event(self, buffer, level):
        l = Log()
        l.loglevel = level
        l.component = 'OVIMCore'
        l.date = datetime.datetime.now()
        l.jobid = 0
        l.log = buffer
        l.save()
        del l
        
        print "%s: %s" % (level, buffer)

    def __init__(self):
        self.log_event("OVIMCore::__INIT__", 'DEBUG')

    def __del__(self):
        pass
    
    def _change_jp_state(self, jp, newstate):
        if jp.state == newstate:
            return
        
        self.log_event("Sate changed to %s" % newstate, "INFO")
        if newstate == 'PRF':
            jp.lastrun = datetime.datetime.now()
        elif (newstate == 'SUC') or (newstate == 'DWE'):
            jp.enddate = datetime.datetime.now()
        
        jp.state = newstate
        jp.save()

    def _create_jobs(self, job_pool):
        self.log_event("Enter in _create_jobs for %s" % job_pool.name,
                        'DEBUG')
        job_pool.cur_taskid += 1
        job_pool.startdate = datetime.datetime.now()
        job_pool.save()
        for vm in job_pool.vmlist.all():
            self.log_event("Will create job for %s vm" % vm.name, 'DEBUG')
            j = Jobs()
            j.vm = vm
            j.type = 'BACKUP'    
            j.mode = job_pool.backupmode
            j.state = 'READY'
            j.backupjobpool = job_pool
            j.storage = vm.vmhost.backup_storage
            j.joppool_id = job_pool.cur_taskid
            j.save()
            del j
            self.log_event("Job added from %s for %s" % (job_pool.name, vm.name), 'INFO')
            self.log_event("done", "DEBUG")
        self.log_event("Done _create_jobs", 'DEBUG')
    
    def _get_jp_satus(self, jp):
        curjobs = Jobs.objects.filter(joppool_id=jp.cur_taskid)
        nbsuccess =  curjobs.filter(state='SUCCESS').count()
        nberror =  curjobs.filter(state='ERROR').count()
        nbperforming =  curjobs.filter(state='PERFORMING').count()
        nbwaiting = curjobs.filter(state='READY').count()
        
        if (nbperforming == 0) and (nbwaiting == 0):
            if (nberror == 0):
                return 'SUC'
            else:
                return 'DWE'
        elif (nberror > 0):
            return 'PWE'
        elif (nberror == 0) and (nbperforming > 0):
            return 'PRF'
        else:
            return 'PRF'
        
        del curjobs
    
    def _garbage_jp(self, jp):
        pass
    
    def _get_jp_timetostart(self, jp):
        now = datetime.datetime.now()
        current_day = int(now.day)
        current_hour = int(now.hour)

        if (jp.state == 'NEW') and (current_hour >= int(jp.startat)):
            return True
        if not jp.lastrun and (current_hour >= int(jp.startat)):
            return True
        else:
            return False
        
        last_run_date = jp.lastrun
        last_run_day = int(last_run_date.day)
        
        if (current_day > last_run_day) and (current_hour >= int(jp.startat)):
            return True
        else:
            return False
    
    def rearm_jp(self, jp):
        now = datetime.datetime.now()
        current_day = int(now.day)
        
        if not jp.lastrun:
            return True
        
        last_run_date = jp.lastrun
        last_run_day = int(last_run_date.day)
        
        return (current_day > last_run_day)
    
    def get_jp_timeout(self, jp):
        now = datetime.datetime.now()
        current_day = int(now.day)
        
        if not jp.startdate:
            return False
        
        startdate = jp.startdate
        startdate_day = int(startdate.day)
            

    def main(self):        
        for jp in BackupJobPool.objects.all():
            if (jp.sate == 'PRF') or (jp.state == 'PWE'):
                pass
                
            if (jp.state == 'SUC') or (jp.state == 'DWE'):
                if self.rearm_jp(jp):
                    self.log_event("New day: positionning RDY trigger", 'DEBUG')
                    self._change_jp_state(jp, 'RDY')
            
            if (jp.state == 'RDY') or (jp.state == 'NEW'):
                if self._get_jp_timetostart(jp):
                    self._garbage_jp(jp)
                    self._create_jobs(jp)
                    self._change_jp_state(jp, 'PRF')
                
            self._change_jp_state(jp, self._get_jp_satus(jp))

def main():
    core = OVIMCore()
    while True:
        core.main()
        time.sleep(60)
    
if __name__ == "__main__":
    try:
        pid = os.fork()
        if pid > 0:
            # exit first parent
            sys.exit(0)
    except OSError, e:
        print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
        sys.exit(1)

    os.chdir("/")
    os.setsid()
    os.umask(0)

    # do second fork
    try:
        pid = os.fork()
        if pid > 0:
            open(PIDFILE,'w').write("%d"%pid)
            sys.exit(0)
    except OSError, e:
        print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
        sys.exit(1)
        
    os.chdir("/opt/OVIM")
    #redirect outputs to a logfile
    sys.stdout = sys.stderr = Log(open(LOGFILE, 'a+'))
    #ensure the that the daemon runs a normal user
    os.setegid(0)
    os.seteuid(0)
    #start the user program here:
    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
    import settings
    from django.core.management import setup_environ
    from django.db.models.loading import get_models
    setup_environ(settings)
    loaded_models = get_models()
    from vimMain.models import BackupJobPool
    from vimMain.models import Jobs
    from vimMain.models import VM, VMHOST
    from vimMain.models import Log
    # start the daemon main loop
    main()
